package com.demo.core.service.base.impl;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.demo.common.IOUtils;
import com.demo.common.Utils;
import com.demo.core.io.FileExtensionFilter;
import com.demo.core.model.File;
import com.demo.core.model.Folder;
import com.demo.core.service.ResourceService;
import com.demo.core.service.exception.FileCreateException;

/**
 * 本地资源服务默认实现类
 * 对本地文件进行操作
 * @author ryuu.kk
 *
 */
public class LocalResourceServiceImpl implements ResourceService {

	/**
	 * 下载文件时一次读取的字节数
	 */
	private static final int BUFFER_SIZE = 1024;
	
	/**
	 * 一次读取字节数
	 */
	private int bufferSize = BUFFER_SIZE;
	
	@Override
	public Folder resourceFolder(String path) {
		
		java.io.File file = new java.io.File(path);
		
		URL url = null;
		try {
			url = file.toURI().toURL();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		return resourceFolder(url, null);
	}
	
	@Override
	public Folder resourceFolder(URL url) {
		return resourceFolder(url, null);
	}

	@Override
	public Folder resourceFolder(URL url, FileFilter filter)  {
		
		Folder root = new Folder();
		// 过滤器为空时,允许所有
		if (filter == null) {
			filter = new FileFilter(){
				@Override
				public boolean accept(java.io.File pathname) {
					return true;
				}
			};
		}
		java.io.File file = null;
		try {
			file = new java.io.File(url.toURI());
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		
		root.setName(file.getName());
		root.setPid(null);
		root.setId(1L);
		resourceFolder(root, file, filter);
		
		return root;
	}

	private void resourceFolder(Folder parent, java.io.File file, FileFilter filter) {
		
		if (file != null) {
			java.io.File[] files = file.listFiles(filter);
			if (files != null && files.length > 0) {
				for (java.io.File f : files) {
					String name = f.getName();
					String title = name;
					if (f.isDirectory()) {
						Folder node = new Folder();
						node.setPid(parent.getId());
						node.setId((long)Utils.random());
						node.setTitle(title);
						node.setName(name);
						parent.addChild(node);
						resourceFolder(node, f, filter);
					} else {
						Long size = f.getTotalSpace();
						File node = new File();
						node.setSize(size);
						node.setName(name);
						node.setTitle(title);
						parent.addFile(node);
					}
				}
			}
		}
	}
	
	private void resourceFolder(StringBuilder parent, Long pid, String path, java.io.File file, FileFilter filter) {
		
		if (file != null) {
			java.io.File[] files = file.listFiles(filter);
			if (files != null && files.length > 0) {
				for (java.io.File f : files) {
					String name = f.getName();
					Long id = (long)Utils.random();
					if (f.isDirectory()) {
						parent.append(String.format("{id:%d, pId:%d, name:'%s', path:'%s', isParent:true},", id, pid, name, path + "/" + name));
						resourceFolder(parent, id, path + "/" + name, f, filter);
					} else {
						Long size = f.getTotalSpace();
						parent.append(String.format("{id:%d, pId:%d, size:%d, name:'%s', path:'%s', isParent:false},", id, pid, size, name, path + "/" + name));
					}
				}
			}
		}
	}

	@Override
	public Folder resourceFolder(URL url, FilterMode filterMode, String... extension) {
		Folder folder = null;
		Boolean include = null;
		if (extension == null) {
			extension = new String[]{};
		}
		switch(filterMode) {
			case include: {
				include = true;
				break;
			} 
			case exclude: {
				include = false;
				break;
			}
			default : {
				// nothing...
			}
		}
		FileExtensionFilter filter = new FileExtensionFilter(extension, include);
		folder = resourceFolder(url, filter);
		return folder;
	}

	@Override
	public File resourceFile(URL url) {
		File file = null;
		try {
			java.io.File f = new java.io.File(url.toURI());
			file = new File();
			String name = f.getName();
			Long size = f.getTotalSpace();
			file.setSize(size);
			file.setName(name);
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return file;
	}

	@Override
	public List<File> resourceFileList(URL url) {
		List<File> fileList = null;
		try {
			java.io.File folder = new java.io.File(url.toURI());
			if (folder.isDirectory()) {
				java.io.File[] files = folder.listFiles(new FileFilter(){
					@Override
					public boolean accept(java.io.File file) {
						return file.isFile();
					}
				});
				
				fileList = new ArrayList<File>();
				if (files != null) {
					for (java.io.File f : files) {
						String name = f.getName();
						Long size = f.length();
						Date modifyDate = new Date(f.lastModified());
						File file = new File();
						file.setName(name);
						file.setSize(size);
						file.setPath(url.getPath());
						file.setModifyDate(modifyDate);
						fileList.add(file);
					}
				}
			}
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return fileList;
	}

	@Override
	public InputStream getStream(URL url) {
		InputStream in = null;
		try {
			java.io.File file = new java.io.File(url.toURI());
			in = new FileInputStream(file);
		} catch (URISyntaxException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return in;
	}

	@Override
	public boolean create(URL url) throws FileCreateException {
		boolean success = false;
		try {
			java.io.File file = new java.io.File(url.toURI());
			if (!file.exists()) {
				success = file.mkdirs();
			}
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return success;
	}

	@Override
	public boolean delete(URL url) throws FileNotFoundException {
		boolean success = false;
		try {
			java.io.File file = new java.io.File(url.toURI());
			if (file.exists()) {
				success = file.delete();
			}
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return success;
	}

	@Override
	public File resourceFile(String path) {
		java.io.File f = new java.io.File(path);
		File file = new File();
		Date modifyDate = new Date(f.lastModified());
		file.setSiteId(f.length());
		file.setName(f.getName());
		file.setModifyDate(modifyDate);
		return file;
	}

	@Override
	public List<File> resourceFileList(String root, String path) {
		List<File> fileList = null;
		java.io.File folder = new java.io.File(root + path);
		if (folder.isDirectory()) {
			java.io.File[] files = folder.listFiles(new FileFilter(){
				@Override
				public boolean accept(java.io.File file) {
					return file.isFile();
				}
			});
			
			fileList = new ArrayList<File>();
			if (files != null) {
				for (java.io.File f : files) {
					String name = f.getName();
					Long size = f.length();
					Date modifyDate = new Date(f.lastModified());
					File file = new File();
					file.setName(name);
					file.setPath(path.charAt(path.length() - 1) == '/' ? path + name : path + "/" + name);
					file.setSize(size);
					file.setModifyDate(modifyDate);
					fileList.add(file);
				}
			}
		}
		return fileList;
	}

	@Override
	public InputStream getStream(String path) throws FileNotFoundException {
		FileInputStream in = null;
		java.io.File file = new java.io.File(path);
		// 判断文件是否
		if (!file.exists()) {
			throw new FileNotFoundException("path :[" + path + "] not found.");
		}
		in = new FileInputStream(file);
		
		return in;
	}
	
	@Override
	public byte[] getContent(String path) throws FileNotFoundException {
		int count;
		byte[] buffer = new byte[bufferSize];
		InputStream inputStream = null;
		ByteArrayOutputStream outputStream = null;
		inputStream = null;
		outputStream = new ByteArrayOutputStream();
        try {
        	inputStream = getStream(path);
			while ((count = inputStream.read(buffer)) > 0) {
				outputStream.write(buffer, 0, count);
			}
		} catch (IOException e) {
			
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					// ignore
				}
			}
			if (outputStream != null) {
				try {
					outputStream.flush();
					outputStream.close();
				} catch (IOException e) {
					// ignore
				}
			}
		}
        
		return outputStream == null? new byte[]{} : outputStream.toByteArray();
	}

	@Override
	public boolean create(String path) throws FileCreateException {
		java.io.File file = new java.io.File(path);
		if (!file.exists()) {
			return file.mkdirs();
		}
		return true;
	}
	
	@Override
	public boolean create(String path, String name, String content) throws FileCreateException {
		create(path);
		// 创建内容
		java.io.FileWriter writer = null;
		if (path.charAt(path.length() - 1) != '/') {
			path = path + '/' + name;
		} else {
			path = path + name;
		}
		try {
			writer = new java.io.FileWriter(new java.io.File(path));
			writer.write(content);
		} catch (IOException e) {
			throw new FileCreateException(path, e.getMessage());
		} finally {
			try {
				writer.flush();
				writer.close();
			} catch (IOException e) {
				throw new FileCreateException(path, e.getMessage());
			}
		}
		return true;
	}
	

	@Override
	public boolean create(String path, String name, java.io.File outputFile) throws FileCreateException {
		if (create(path)) {
			// 创建内容
			if (path.charAt(path.length() - 1) != '/') {
				path = path + '/' + name;
			} else {
				path = path + name;
			}
			java.io.File file = new java.io.File(path);

			if (!outputFile.renameTo(file)) {
				BufferedInputStream in = null;
				BufferedOutputStream out = null;
				try {
					in = new BufferedInputStream(new FileInputStream(outputFile));
					out = new BufferedOutputStream(new FileOutputStream(file));
					IOUtils.copy(in, out);
				} catch (FileNotFoundException e) {
					throw new FileCreateException(outputFile, e.getMessage());
				} catch (IOException e) {
					throw new FileCreateException(outputFile, e.getMessage());
				} finally {
					if (in != null) {
						try {
							in.close();
						} catch (IOException e) {
							// ignore
						}
					}
					if (out != null) {
						try {
							out.flush();
							out.close();
						} catch (IOException e) {
							// ignore
						}
					}
				}
			}
		}
		return true;
	}
	

	@Override
	public boolean delete(String path) throws FileNotFoundException {
		java.io.File file = new java.io.File(path);
		if (file.exists()) {
			return deleteAll(file);
		} 
		throw new FileNotFoundException();
	}
	
	public boolean deleteAll(java.io.File file) {
		if (file != null && file.exists()) {
			if (file.isDirectory()) {
				java.io.File[] files = file.listFiles();
				for (java.io.File f : files) {
					deleteAll(f);
				}
			}
			return file.delete();
		}
		return false;
	}

	@Override
	public String buildJson(URL url, FileFilter filter) {
		
		if (url == null) {
			return "";
		}
		StringBuilder root = new StringBuilder();
		// 过滤器为空时,允许所有
		if (filter == null) {
			filter = new FileFilter(){
				@Override
				public boolean accept(java.io.File pathname) {
					return true;
				}
			};
		}
		java.io.File file = null;
		try {
			file = new java.io.File(url.toURI());
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		String name = file.getName();
		String path = "/" + name;
		Long pid = null;
		Long id = 1L;
		root.append(String.format("[{id:%d, pId:%d, name:'%s', open:true},", id, pid, name));
		resourceFolder(root, id, path, file, filter);
		// 去掉最后","
		return root.substring(0, root.length() - 1) + "]";
	}
	
	public static final void main(String[] args) {
		LocalResourceServiceImpl service = new LocalResourceServiceImpl();
		String path = "C:\\back\\AliWangWang";
		java.io.File file = new java.io.File(path);
		String json = "";
		try {
			//folder = service.resourceFolder(file.toURI().toURL());
			json = service.buildJson(file.toURI().toURL(), null);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		
		System.out.print(json);
	}

	@Override
	public String buildJson(String path, FileFilter filter) {
		if (path == null) {
			return "";
		}
		StringBuilder root = new StringBuilder();
		// 过滤器为空时,允许所有
		if (filter == null) {
			filter = new FileFilter(){
				@Override
				public boolean accept(java.io.File pathname) {
					return true;
				}
			};
		}
		java.io.File file = null;
		file = new java.io.File(path);
		String name = file.getName();
		String spath = "/" + name;
		Long pid = null;
		Long id = 1L;
		root.append(String.format("[{id:%d, pId:%d, name:'%s', path:'%s', open:true, isParent:true},", id, pid, name, spath));
		resourceFolder(root, id, spath, file, filter);
		// 去掉最后","
		//root.substring(0, root.length() - 2);
		//root.append("]");
		return root.substring(0, root.length() - 1) + "]";
	}

	public void setBufferSize(int bufferSize) {
		this.bufferSize = bufferSize;
	}
}
